import sys, os
import time
from threading import Thread, Lock

sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from bitbrook.brook import Brook
from bitbrook.tracker_manager import TrackerManager
from bitbrook.connection_handler import ConnectionHandler
#from bitbrook.simple_leech_strategy import SimpleLeechStrategy
from bitbrook.rarest_chunk_strategy import RarestChunkStrategy
from bitbrook.network import Network
from bitbrook.network_builder import NetworkBuilder
#from bitbrook.utilities.limited_socket import LSocket

TRACKER_PORT = 25784

class PeerFacade(Thread):
    def __init__(self, brookfile, listening_port, ID):
        super(PeerFacade, self).__init__()
        #needed for thread stopping
        self._shutdown = False
        self._shutdown_signal = Lock()
        
        self.ID = ID
        self._listening_port = int(listening_port)
        #self._my_addr = socket.gethostbyname(socket.gethostname())
        #due to testing on 1 machine only this hack is applied
        self._my_addr = ("127.0.0.1", self._listening_port)
        #ID is added to put the brook in a sub-dir for easier testing
        #Brook objected is a handle to the _brook and the file it represent
        self._brook = Brook(brookfile, ID)
        #Network is just a class to handle peers
        self._network = Network(self._my_addr, self._brook)
        self._brook.verify_brook(self._network)
        #TrackerManager is a thread to handle the tracker, it's a thread because it needs
        #to send an UPDATE every 4min (sending it every 3 min)
        #shutdown() will make it issue a LEAVE and then exit
        print "Initializing TM"
        self._tracker_manager = TrackerManager(self._brook.tracker, TRACKER_PORT, self._brook._brook_id, self._listening_port)
        print "Initializing NB"
        #Network Builder
        self._network_builder = NetworkBuilder(self._network, self._brook)
        print "initializing CH"
        #ConnectionHandler
        self._connection_handler = ConnectionHandler(self._my_addr, self._brook, self._network_builder, self._network)
        
    def run(self):
        print "Starting TM"
        self._tracker_manager.start()
        time.sleep(2)
        print "Requesting peers"
        peers = self._tracker_manager.request_peers()
        self._network.add_peer_list(peers)
        print "Starting CH"
        self._connection_handler.start()
        time.sleep(2)
        print "Starting NB"
        self._network_builder.start()
        time.sleep(2)
        if not self._brook.completed:
            print "Initialize Leech Strategy"
            #self._leech_strategy = SimpleLeechStrategy(self._brook, self._network)
            self._leech_strategy = RarestChunkStrategy(self._brook, self._network)
            print "Starting Leech Strategy"
            self._leech_strategy.start()
        with self._shutdown_signal:
            while not self._shutdown:
                if self._brook.completed:
                    print "I'm a seeder: ", self.ID
                time.sleep(10)
        print ""
        self._connection_handler.shutdown()
        self._connection_handler.join()
        print "Connection Manager shutdown: done"
        self._tracker_manager.shutdown()
        self._tracker_manager.join()
        print "Tracker Manager shutdown: done"
        self._network_builder.shutdown()
        self._network_builder.join()
        print "Network Builder shutdown: done"
    
    def shutdown(self, block = True):
        self._shutdown = True
        if block:
            self._shutdown_signal.acquire()
            self._shutdown_signal.release()
    
    def set_upload(self, speed):
        pass
        #LSocket.set_upload_limit(speed)
    
    def set_download(self, speed):
        pass
        #LSocket.set_download_limit(speed)